#include "GUISystem.h"
#include "TerrainSystem.h"
#include "frmMenuBar.h"
#include "frmTerrain.h"
#include "frmPhysics.h"
#include "frmPaging.h"
#include "GameObjectManager.h"

#include <iostream>
#include <iomanip>
#include <sstream> 

CEGUI::Renderer* GUISystem::mGUIRenderer = NULL;
CEGUI::System* GUISystem::mGUISystem = NULL;
RenderWindow* GUISystem::mWindow = NULL;
SceneManager* GUISystem::mSceneMgr = NULL;
GameState* GUISystem::gameState = NULL;
CEGUI::Window* GUISystem::mainWindow = NULL;

frmMenuBar *GUISystem::mfrmMenuBar = NULL;
frmTerrain *GUISystem::mfrmTerrain = NULL;
frmPhysics *GUISystem::mfrmPhysics = NULL;
frmObjects *GUISystem::mfrmObjects = NULL;
frmScene *GUISystem::mfrmScene = NULL;
frmPaging *GUISystem::mfrmPaging = NULL;

GUISystem::GUISystem() 
{
	//GameSystemManager::getSingleton()->cre
	mGUIRenderer = NULL;
	mGUISystem = NULL;
	mWindow = GameSystemManager::getSingleton()->getOgre()->getWindow();
	mSceneMgr = GameSceneManager::getSingleton()->getSceneManager();

	mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr);
	mGUISystem = new CEGUI::System(mGUIRenderer);

	CEGUI::Logger::getSingleton().setLoggingLevel(CEGUI::Informative);
  
	//Load skin
	CEGUI::Imageset* taharezImages = CEGUI::ImagesetManager::getSingleton().createImageset("TaharezLook.imageset");
	CEGUI::WidgetLookManager::getSingleton().parseLookNFeelSpecification("TaharezLook.looknfeel");
	CEGUI::SchemeManager::getSingleton().loadScheme("TaharezLookSkin.scheme"); //TaharezLookSkin
	CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow");

	//Load Game GUI layout
	CEGUI::Window* sheet = CEGUI::WindowManager::getSingleton().loadWindowLayout((CEGUI::utf8*)"Menu2.layout");
	mGUISystem->setGUISheet(sheet);
	
	setupGUI();

	subscribeEvents();

	mfrmMenuBar = new frmMenuBar();
	mfrmPhysics = new frmPhysics();
	mfrmTerrain = new frmTerrain();
	mfrmObjects = new frmObjects();
	mfrmScene = new frmScene();	
	mfrmPaging = new frmPaging();	

}
void GUISystem::showLoader(bool show) {
	CEGUI::FrameWindow* frm = (CEGUI::FrameWindow*)CEGUI::WindowManager::getSingleton().getWindow("Loader");
	frm->setVisible(show);
	GameSystemManager::getSingleton()->getOgre()->getRoot()->renderOneFrame();
	Ogre::WindowEventUtilities::messagePump();
	//mGUIRenderer->
}	
/*
void GUISystem::setProgressBarValue(float value) {
	CEGUI::FrameWindow* frm = (CEGUI::FrameWindow*)CEGUI::WindowManager::getSingleton().getWindow("Loader");
	if(!frm->isVisible())
		frm->setVisible(true);

	CEGUI::ProgressBar* prg = (CEGUI::ProgressBar*)CEGUI::WindowManager::getSingleton().getWindow("Loader/prgBar");
	prg->setProgress(value);
	GameSystemManager::getSingleton()->getOgre()->getRoot()->renderOneFrame();
}
*/

CEGUI::Window* GUISystem::addImageToControl(Ogre::String imageName,Ogre::String windowName,Ogre::String imageSetName)
{
	//Create imageset
	//CEGUI::ImagesetManager::getSingleton().createImageset("temp.imageset"); 
	//CEGUI::Imageset* imageSet = CEGUI::ImagesetManager::getSingleton().getImageset("temp");
	
	//CEGUI::Texture *ceguiTex = mGUIRenderer->createTexture("tex","ET");
	//ceguiTex->loadFromFile(imageName,"ET");
	//imageSet->loa ->setTexture(ceguiTex);

	//CEGUI::Window* targetWindow = CEGUI::WindowManager::getSingleton().getWindow("Terrain/imgHeightMapPreview");
	//const CEGUI::Image *image = CEGUI::PropertyHelper::stringToImage(imageName);
	//targetWindow->setProperty("Image", CEGUI::PropertyHelper::imageToString(&imageSet->getImage(image)));
	if(CEGUI::ImagesetManager::getSingleton().isImagesetPresent(imageSetName)) {
		CEGUI::ImagesetManager::getSingleton().destroyImageset(imageSetName);
		//CEGUI::Imageset* is CEGUI::ImagesetManager::getSingleton().getImageset("SelfImage1");
		CEGUI::ImagesetManager::getSingleton().createImagesetFromImageFile(imageSetName, imageName);
		//if(!is->isImageDefined(imageName))
		
			
	} else {
		CEGUI::ImagesetManager::getSingleton().createImagesetFromImageFile(imageSetName, imageName);
	}
	
	//Window* me = static_cast<Window*>(mWindow->getChild("CreditsWindow/SelfImage"));
	CEGUI::Window* targetWindow = CEGUI::WindowManager::getSingleton().getWindow(windowName);
	targetWindow->setProperty("Image", "set:" + imageSetName + " image:full_image"); //SelfImage1
	
	//CEGUI::ImagesetManager::getSingleton().destroyImageset("SelfImage1");

    return targetWindow;
}

void GUISystem::setStaticImageObject(Ogre::String imageSetName,Ogre::String imageName,Ogre::String windowName)
{
	CEGUI::ImagesetManager::getSingleton().createImageset(imageSetName + ".imageset"); 
	CEGUI::Imageset* imageSet = CEGUI::ImagesetManager::getSingleton().getImageset(imageSetName);
	CEGUI::Window* si = CEGUI::WindowManager::getSingleton().getWindow(windowName);
	
    si->setProperty("Image", CEGUI::PropertyHelper::imageToString(&imageSet->getImage(imageName)));
	si->setSize(CEGUI::UVector2( si->getSize().d_x, si->getSize().d_y ));
}

void GUISystem::updateObjectsWindow() {
	mfrmObjects->updateControls();
}

void GUISystem::setupGUI() {
	//Set password textbox mask
	((CEGUI::Editbox*)CEGUI::WindowManager::getSingleton().getWindow("Client/txtPass"))->setTextMasked(true);
	
	((CEGUI::Window*)CEGUI::WindowManager::getSingleton().getWindow("BackGround"))->setVisible(false);
	((CEGUI::FrameWindow*)CEGUI::WindowManager::getSingleton().getWindow("Loader"))->setVisible(false);

	//Set Main Menu's background image
	setStaticImageObject("LoaderImages","btnNormal","BackGround");
	
	//Reset cursor position
	CEGUI::MouseCursor::getSingleton().setPosition(CEGUI::Point(CEGUI::Vector2(0,0)));

	GameSystemManager::getOgre()->getRoot()->renderOneFrame();

/*
	//Fill terrain listbox with heightmaps files
	CEGUI::Listbox* lbox = (CEGUI::Listbox*) CEGUI::WindowManager::getSingleton().getWindow("Terrain/List");
	Ogre::StringVectorPtr groupNamesList = ResourceGroupManager::getSingleton().findResourceNames("ET","ETterrain*.png");
	//groupNamesList.
	std::vector<Ogre::String>::iterator itGroup = groupNamesList.begin();
	
	CEGUI::ListboxTextItem* item;
    for(; itGroup != groupNamesList.isNull(); ++itGroup) 
    {        
		item = new CEGUI::ListboxTextItem(*itGroup);
        item->setSelectionBrushImage(LOOKNFEEL, BRUSH);
        item->setSelectionColours(SELECTED_COLOR);
        item->setTextColours (BASIC_COLOR);
        lbox->addItem(item);  
	}
*/

	//.getResourceDeclarationList("General");
	//CEGUI::Combobox* cbox = (CEGUI::Combobox*) wMgr->getWindow("MeshViewer/GroupBox");
	//std::vector<Ogre::String>::iterator itGroup = groupNamesList.begin();
	//for itGroup
}
bool GUISystem::isCheckBoxSelected(std::string checkBoxName) {
	CEGUI::Checkbox* w = (CEGUI::Checkbox*)CEGUI::WindowManager::getSingleton().getWindow(checkBoxName);
	return w->isSelected();
}
CEGUI::Window* GUISystem::getElement(const char* menuItem)
{
	//wmgr.getWindow((CEGUI::utf8*)"Menu/btnExit")
	return CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)menuItem);
}

CEGUI::Window* GUISystem::getMainWindow()
{
	return CEGUI::WindowManager::getSingleton().getWindow("Menu");
}

const char* GUISystem::EditBoxToChr(CEGUI::String EditBoxName)
{
	CEGUI::Editbox* editbox = (CEGUI::Editbox*)CEGUI::WindowManager::getSingleton().getWindow(EditBoxName);
	return editbox->getText().c_str();
}
float GUISystem::EditBoxToFloat(std::string EditBoxName) //CEGUI::String 
{
	CEGUI::Editbox* editbox = (CEGUI::Editbox*)CEGUI::WindowManager::getSingleton().getWindow(EditBoxName);
	float result = atof(editbox->getText().c_str()); //StringConverter::parseReal(
	if(!result)
		return NULL;
	//Ogre::Math::r
	//float f;
    //sprintf(f,"%f",result)
	return result;
}
bool GUISystem::CheckBoxToBool(std::string checkBoxName) //CEGUI::String 
{
	CEGUI::Checkbox* checkbox = (CEGUI::Checkbox*)CEGUI::WindowManager::getSingleton().getWindow(checkBoxName);
	return checkbox->isSelected();
}

void GUISystem::destroyGUI()
{
	if(mGUISystem)
	{
		delete mGUISystem;
		mGUISystem = 0;
	}
	if(mGUIRenderer)
	{
		//delete mGUIRenderer;
		mGUIRenderer = 0;
	}
}

bool GUISystem::windowMoved(const CEGUI::EventArgs& e)
{
	return false;
}

GUISystem::~GUISystem()
{
	destroyGUI();
}

CEGUI::MouseButton GUISystem::convertOISMouseButtonToCegui(int buttonID)
{
	switch (buttonID)
	{
		case 0: return CEGUI::LeftButton;
		case 1: return CEGUI::RightButton;
		case 2:	return CEGUI::MiddleButton;
		case 3: return CEGUI::X1Button;
		default: return CEGUI::LeftButton;
	}
}
void GUISystem::hideCursor() {
	CEGUI::MouseCursor::getSingleton().hide();
}
void GUISystem::showCursor() {
	CEGUI::MouseCursor::getSingleton().show();
}

void GUISystem::updateMouseMoved(int x, int y) {
	CEGUI::System::getSingleton().injectMouseMove( x, y );

	CEGUI::Window *root = CEGUI::WindowManager::getSingleton().getWindow("root");
	CEGUI::Window *w;
	
	CEGUI::Vector2 mousePos = CEGUI::MouseCursor::getSingleton().getPosition();

	w = root->getChildAtPosition(mousePos);
	
	if(w) {
		GameObjectManager::getSingleton()->mouseMovedNotification(true,x,y);
	} else {
		GameObjectManager::getSingleton()->mouseMovedNotification(false,x,y);
	}
	
	if(mousePos.d_y < 100.0f) {
		CEGUI::Window* wndMenuBar = CEGUI::WindowManager::getSingleton().getWindow("MenuBar");
		wndMenuBar->setVisible(true);
	} else { //if (y > 1.0f) 
		CEGUI::Window* wndMenuBar = CEGUI::WindowManager::getSingleton().getWindow("MenuBar");
		wndMenuBar->setVisible(false);
	}

}
void GUISystem::updateGameObjects() {
	mfrmObjects->fillObjectsList();

}

void GUISystem::fillGUIFromConfig() {
	mfrmScene->fillGUIFromConfig();
}

void GUISystem::updatePagedObjects() {
	mfrmPaging->populatePagedTreesList();
	mfrmPaging->populatePagedGrassList();
}

void GUISystem::updateMouseButtonDown(unsigned int button) {
	CEGUI::System::getSingleton().injectMouseButtonDown(convertOISMouseButtonToCegui(button));
	CEGUI::Window *root = CEGUI::WindowManager::getSingleton().getWindow("root");
	CEGUI::Window *w;
	
	w = root->getChildAtPosition(CEGUI::MouseCursor::getSingleton().getPosition());
	
	if(w) {
		GameSystemManager::getSingleton()->getTerrain()->mouseButtonDownNotification(true,button);
		//static_cast<TerrainSystem*>(GameSystemManager::getSingleton()->getSystem("TerrainSystem"))->mouseButtonDownNotification(true,button);
		GameObjectManager::getSingleton()->mouseButtonDownNotification(true,button);
	} else {
		GameSystemManager::getSingleton()->getTerrain()->mouseButtonDownNotification(false,button);
		//static_cast<TerrainSystem*>(GameSystemManager::getSingleton()->getSystem("TerrainSystem"))->mouseButtonDownNotification(false,button);
		GameObjectManager::getSingleton()->mouseButtonDownNotification(false,button);
	}
}

void GUISystem::updateMouseButtonUp(unsigned int button) {
	
	CEGUI::System::getSingleton().injectMouseButtonUp(convertOISMouseButtonToCegui(button));
	
	CEGUI::Window *root = CEGUI::WindowManager::getSingleton().getWindow("root");
	CEGUI::Window *w;
	w = root->getChildAtPosition(CEGUI::MouseCursor::getSingleton().getPosition());

	if(w) //Clicking over a window disable the action
		GameObjectManager::getSingleton()->mouseButtonUpNotification(true,button);
	else
		GameObjectManager::getSingleton()->mouseButtonUpNotification(false,button);

	GameSystemManager::getSingleton()->getTerrain()->mouseButtonUpNotification(false,button);
	//static_cast<TerrainSystem*>(GameSystemManager::getSingleton()->getSystem("TerrainSystem"))->mouseButtonUpNotification(false,button);
}
void GUISystem::updateKeyboardKeyPressed(OIS::KeyEvent evt) {
	CEGUI::System::getSingleton().injectChar( evt.text );
	CEGUI::System::getSingleton().injectKeyDown(  evt.key );
}
void GUISystem::updateKeyboardKeyReleased(OIS::KeyEvent evt) {
	CEGUI::System::getSingleton().injectChar( evt.text );
	CEGUI::System::getSingleton().injectKeyUp( evt.key );
}

std::string GUISystem::getSelectedListItem(const CEGUI::EventArgs& e,std::string windowName) {
    const CEGUI::WindowEventArgs& wEventArgs = static_cast<const CEGUI::WindowEventArgs&>(e);
    CEGUI::Listbox* list = static_cast<CEGUI::Listbox*>(wEventArgs.window);
    const CEGUI::String Name = list->getName ();
    size_t selCount = list->getSelectedCount ();
    if (selCount == 1)
    {
        CEGUI::ListboxTextItem* item =  (CEGUI::ListboxTextItem*) list->getFirstSelectedItem ();
        const unsigned int pos = StringConverter::parseUnsignedInt (item->getText().c_str ());   

        {
			const char *matName = item->getText().c_str();;
            //mSelector->loadMaterial (matName, true);
			item->setSelected(true);

            CEGUI::WindowManager& wMgr = CEGUI::WindowManager::getSingleton();
            CEGUI::Listbox* matList  =  static_cast<CEGUI::Listbox*> (CEGUI::WindowManager::getSingleton().getWindow(windowName));
            //matList->clearAllSelections();
            CEGUI::ListboxTextItem* itemMat = (CEGUI::ListboxTextItem*) matList->findItemWithText(matName, 0);
            matList->setItemSelectState (itemMat, true);
			return matName;
		}
	}
	return "";	
}

void GUISystem::selectItemCombobox(std::string cmbName, std::string cmbItem) {
	CEGUI::Combobox* cmb = (CEGUI::Combobox*) CEGUI::WindowManager::getSingleton().getWindow(cmbName);
	CEGUI::ListboxTextItem* item =  (CEGUI::ListboxTextItem*) cmb->findItemWithText(cmbItem,0);
	cmb->setItemSelectState(item,true);
	cmb->requestRedraw();
	cmb->setText(cmbItem);
	item->setSelected(true);
	item->setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush");
}

////////////////////////////////////////////////////////////////////////////////////////////////////////
//All GUI events are subscribed here

bool GUISystem::subscribeEvents() {
	////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//Subscribe to events:
	//
	//CEGUI::Window* ProgressBar = CEGUI::WindowManager::getSingleton().getWindow("MainMenu/ProgressgBar");
	//ProgressBar->subscribeEvent(CEGUI::ProgressBar::eve,CEGUI::Event::Subscriber(&myCEGUI::evtClientConnect_click,this));

	////////////////////////////////////////////////////////////////////////////////////////////////////
	//Subsribe GUI network events
	CEGUI::Window* btnConnect = CEGUI::WindowManager::getSingleton().getWindow("Client/btnConnect");
	btnConnect->subscribeEvent(CEGUI::PushButton::EventClicked,CEGUI::Event::Subscriber(&GUISystem::evtClientConnect_click,this));
	
	CEGUI::Window* btnQuit = CEGUI::WindowManager::getSingleton().getWindow("Client/btnExit");
	btnQuit->subscribeEvent(CEGUI::PushButton::EventClicked,CEGUI::Event::Subscriber(&GUISystem::evtClientQuit_click,this));
	
	CEGUI::Window* wndClientClose = CEGUI::WindowManager::getSingleton().getWindow("Client");
	wndClientClose->subscribeEvent(CEGUI::FrameWindow::EventCloseClicked,CEGUI::Event::Subscriber(&GUISystem::evtClientClose_click,this));

	return true;
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
//Multiplayer GUI Events
bool GUISystem::evtClientConnect_click(const CEGUI::EventArgs& e)
{
	return true;
}
bool GUISystem::evtClientQuit_click(const CEGUI::EventArgs& e)
{
	CEGUI::Window* w = CEGUI::WindowManager::getSingleton().getWindow("Client");
	w->setVisible(false);
	return true;
}
bool GUISystem::evtClientClose_click(const CEGUI::EventArgs& e)
{
	CEGUI::Window* w = CEGUI::WindowManager::getSingleton().getWindow("Client");
	w->setVisible(false);
	return true;
}
